﻿#include <vector>
#include <Eigen/Dense>
#include <cmath>
#include "src/Core/Matrix.h"

using Point = std::pair<double, double>;

// 多项式插值：f(x) = Σαᵢxⁱ
extern Eigen::VectorXd polynomialInterpolation(const std::vector<Point>& points);

/**
 * @brief 用拟合系数计算任意x处的拟合值
 * @param x 待评估的x
 * @param coefficients 拟合系数 a = [a0, a1, ..., am]^T
 * @return 拟合多项式f(x)的值
 */
extern double evaluatePolynomial(const Eigen::VectorXd& coeffs, double x);

/**
 * @brief 高斯基函数 g_i(x) = exp(-(x - x_i)^2/(2*sigma^2))
 * @param x 自变量
 * @param center 基函数中心（插值点的x坐标）
 * @return 基函数在x处的取值
 */
double gaussianBasis(double x, double center, double sigma);

// Gauss基函数插值：f(x) = b₀ + Σbᵢexp(-(x-xᵢ)²/(2σ²))
// 当变量数 > 方程数时，使用Tikhonov正则化作为约束
extern Eigen::VectorXd gaussBasisInterpolation(const std::vector<Point>& points, double sigma = 1.0);

/**
 * @brief 用插值系数计算任意x处的插值值
 * @param x 待插值的x
 * @param points 原始插值节点（用于获取基函数中心）
 * @param coefficients 插值系数 b = [b0, b1, ..., b_{m-1}]^T
 * @return 插值函数f(x)的值
 */
double evaluateGaussBasis(const Eigen::VectorXd& coefficients, const std::vector<Point>& points, double x, double sigma);

/**
 * @brief 计算所有节点的平均相邻间距（全局密度度量）
 * @param points 插值节点（x坐标需按升序排列，若无序需先排序）
 * @return 平均间距 d_avg
 */
double computeGlobalAvgSpacing(const std::vector<Point>& points);

/**
 * @brief 全局自适应sigma：σ = k * d_avg（k为经验系数，默认1.2）
 * @param points 插值节点
 * @param k 调节系数（建议1.0~1.5，k越大覆盖范围越广）
 * @return 自适应全局sigma
 */
double adaptiveGlobalSigma(const std::vector<Point>& points, double k = 1.2);

/**
 * @brief 幂基函数最小二乘拟合（逼近型）
 * @param points 输入数据点集合（个数n ≥ 2）
 * @param max_degree 拟合多项式最高次数m（需满足 0 ≤ m < points.size()）
 * @return 拟合系数 a = [a0, a1, ..., am]^T（a0是常数项，am是x^m的系数）
 */
extern Eigen::VectorXd polynomialLeastSquaresFitting(const std::vector<Point>& points, int max_degree);

/**
 * @brief 岭回归拟合（带L2正则项的幂基函数最小二乘）
 * @param points 输入数据点集合（个数n ≥ 2）
 * @param max_degree 拟合多项式最高次数m（0 ≤ m < n）
 * @param lambda 正则化参数（λ ≥ 0，λ=0退化为普通最小二乘）
 * @return 拟合系数 a = [a0, a1, ..., am]^T
 */
extern Eigen::VectorXd ridgeRegressionFitting(const std::vector<Point>& points, int max_degree, double lambda);

// 生成拟合曲线上的n个点（核心功能：用于绘图）
// 输入：拟合函数、原始点x范围、需要生成的点数n
// 输出：均匀分布的n个拟合点
extern std::vector<Point> generateFitPoints(std::function<double(double)> fitFunction, const std::vector<Point>& originalPoints, int n);

//---------------------------------作业3----------------------------------

/**
 * @brief 生成等距参数 t（简单参数化）
 * @param points 输入点集（按顺序排列）
 * @return 等距 t 向量：t_i = i/(n-1) ∈ [0,1]（归一化，便于计算）
 */
extern std::vector<double> generateEquidistantT(const std::vector<Point>& points);

/**
 * @brief 生成弦长参数 t（几何均匀参数化）
 * @param points 输入点集（按顺序排列）
 * @return 累积弦长 t 向量：t_0=0，t_i = t_{i-1} + 两点间欧氏距离（归一化）
 */
extern std::vector<double> generateChordLengthT(const std::vector<Point>& points);

/**
 * @brief 生成Centripetal（向心）参数t
 * @param points 输入点集（按曲线顺序排列）
 * @param alpha 向心参数（α∈(0,1]，默认0.5，α=1退化为弦长参数化）
 * @return 归一化到[0,1]的参数t向量
 */
extern std::vector<double> generateCentripetalT(const std::vector<Point>& points, double alpha = 0.5);

/**
 * @brief 生成Foley-van Dam参数t（考虑线段夹角，避免拐点扭曲）
 * @param points 输入点集（按曲线顺序排列）
 * @return 归一化到[0,1]的参数t向量
 */
extern std::vector<double> generateFoleyT(const std::vector<Point>& points);

/**
 * @brief 使用最小二乘拟合参数曲线（低次逼近，m < n-1）
 * @param points 输入点集（n 个点）
 * @param max_degree 多项式最高次数 m（x(t) 和 y(t) 均为 m 次）
 * @return 参数曲线系数（a 对应 x(t)，b 对应 y(t)）
 */
extern std::pair<Eigen::VectorXd, Eigen::VectorXd> fitParametricLeastSquares(const std::vector<Point>& points, int max_degree, const std::vector<double>& t);

/**
 * @brief 评估拟合的参数曲线在任意 t 处的点
 * @param t_eval 待评估的参数 t
 * @param coeffs 拟合得到的参数曲线系数
 * @return (x(t_eval), y(t_eval))
 */
extern Point evaluateFittedCurve(double t_eval, const std::pair<Eigen::VectorXd, Eigen::VectorXd>& coeffs);

